package cloud.shyidong.core.controller;

import cloud.shyidong.core.dao.BaseDao;
import cloud.shyidong.core.entity.BaseEntity;
import cloud.shyidong.core.request.*;
import cloud.shyidong.core.response.PageResponse;
import cloud.shyidong.core.service.BaseService;
import cloud.shyidong.core.util.SpringUtils;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import javax.validation.Valid;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

/**
 * @Description TODO
 * @Author syd
 * @Date 2023/3/27
 */
@Slf4j
public class AbstractController<S extends BaseService, D extends BaseDao, T extends BaseEntity, ID extends IdRequest, IQ extends InsertRequest, UQ extends UpdateRequest, PQ extends PageRequest> implements BaseController<S, D, T, ID, IQ, UQ, PQ> {
    
    private S s;
    
    protected S getService() {
        if (this.s == null) {
            Type type = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
            this.s = (S) SpringUtils.getBean((Class) type);
        }
        return this.s;
    }
    
    @Override
    @PostMapping(value = "/insert", consumes = {"application/json"})
    public T insert(@RequestBody @Valid IQ insertRequest) {
        if (log.isDebugEnabled()) {
            log.debug("insert param >>> {}", JSON.toJSONString(insertRequest));
        }
        return (T) this.getService().insert(insertRequest);
    }
    
    @Override
    @PostMapping(value = "/update", consumes = {"application/json"})
    public T update(@RequestBody @Valid UQ updateRequest) {
        if (log.isDebugEnabled()) {
            log.debug("update param >>> {}", JSON.toJSONString(updateRequest));
        }
        return (T) this.getService().update(updateRequest);
    }
    
    @Override
    @PostMapping(value = "/delete", consumes = {"application/json"})
    public T delete(@RequestBody @Valid ID idRequest) {
        if (log.isDebugEnabled()) {
            log.debug("delete param >>> {}", JSON.toJSONString(idRequest));
        }
        return (T) this.getService().delete(idRequest);
    }
    
    @Override
    @PostMapping(value = "/deletes", consumes = {"application/json"})
    public Map<String, Object> deletes(@RequestBody @Valid IdsRequest<ID> idsRequest) {
        if (log.isDebugEnabled()) {
            log.debug("deletes param >>> {}", JSON.toJSONString(idsRequest));
        }
        return this.getService().deletes(idsRequest);
    }
    
    @Override
    @PostMapping(value = "/enable", consumes = {"application/json"})
    public T enable(@RequestBody @Valid ID idRequest) {
        if (log.isDebugEnabled()) {
            log.debug("enable param >>> {}", JSON.toJSONString(idRequest));
        }
        return (T) this.getService().enable(idRequest);
    }
    
    @Override
    @PostMapping(value = "/enables", consumes = {"application/json"})
    public Map<String, Object> enables(@RequestBody @Valid IdsRequest<ID> idsRequest) {
        if (log.isDebugEnabled()) {
            log.debug("enables param >>> {}", JSON.toJSONString(idsRequest));
        }
        return this.getService().enables(idsRequest);
    }
    
    @Override
    @PostMapping(value = "/disable", consumes = {"application/json"})
    public T disable(@RequestBody @Valid ID idRequest) {
        if (log.isDebugEnabled()) {
            log.debug("disable param >>> {}", JSON.toJSONString(idRequest));
        }
        return (T) this.getService().disable(idRequest);
    }
    
    @Override
    @PostMapping(value = "/disables", consumes = {"application/json"})
    public Map<String, Object> disables(@RequestBody @Valid IdsRequest<ID> idsRequest) {
        if (log.isDebugEnabled()) {
            log.debug("disables param >>> {}", JSON.toJSONString(idsRequest));
        }
        return this.getService().disables(idsRequest);
    }
    
    @Override
    @PostMapping(value = "/up", consumes = {"application/json"})
    public T up(@RequestBody @Valid ID idRequest) {
        if (log.isDebugEnabled()) {
            log.debug("up param >>> {}", JSON.toJSONString(idRequest));
        }
        return (T) this.getService().up(idRequest);
    }
    
    @Override
    @PostMapping(value = "/ups", consumes = {"application/json"})
    public Map<String, Object> ups(@RequestBody @Valid IdsRequest<ID> idsRequest) {
        if (log.isDebugEnabled()) {
            log.debug("ups param >>> {}", JSON.toJSONString(idsRequest));
        }
        return this.getService().ups(idsRequest);
    }
    
    @Override
    @PostMapping(value = "/down", consumes = {"application/json"})
    public T down(@RequestBody @Valid ID idRequest) {
        if (log.isDebugEnabled()) {
            log.debug("down param >>> {}", JSON.toJSONString(idRequest));
        }
        return (T) this.getService().down(idRequest);
    }
    
    @Override
    @PostMapping(value = "/downs", consumes = {"application/json"})
    public Map<String, Object> downs(@RequestBody @Valid IdsRequest<ID> idsRequest) {
        if (log.isDebugEnabled()) {
            log.debug("downs param >>> {}", JSON.toJSONString(idsRequest));
        }
        return this.getService().downs(idsRequest);
    }
    
    @Override
    @GetMapping(value = "/view")
    public Map<String, Object> view(@Valid ID idRequest) {
        if (log.isDebugEnabled()) {
            log.debug("view param >>> {}", JSON.toJSONString(idRequest));
        }
        return this.getService().view(idRequest);
    }
    
    @Override
    @GetMapping(value = "/search")
    public List<T> search(PQ pageRequest) {
        if (log.isDebugEnabled()) {
            log.debug("search param >>> {}", JSON.toJSONString(pageRequest));
        }
        return this.getService().search(pageRequest);
    }
    
    @Override
    @GetMapping(value = "/page")
    public PageResponse<Map<String, Object>> page(PQ pageRequest) {
        if (log.isDebugEnabled()) {
            log.debug("page param >>> {}", JSON.toJSONString(pageRequest));
        }
        return this.getService().page(pageRequest);
    }
    
}
